import { Directive, Input, ElementRef, Optional, Inject, OnChanges, SimpleChanges, Renderer2 } from '@angular/core';
import { DOCUMENT } from '@angular/common';
import { IconService } from './icon.service';
import { IconDefinition, RenderMeta, ThemeType } from '../types';
import { getNameAndNamespace, alreadyHasThemeSuffix, warn, isIconDefinition, withThemeSuffix } from '../utils';

@Directive({
  selector: '[nsIcon]'
})
export class IconDirective implements OnChanges {

  @Input() nsName: string | IconDefinition = '';
  @Input() nsTheme: ThemeType = 'outline'; // 默认主题是outline, 用户不传nsTheme时
  @Input() nsTwoToneColor: string = '';

  constructor(
    private element: ElementRef,
    private iconService: IconService,
    private renderer: Renderer2,
    @Optional() @Inject(DOCUMENT) private document: any
    ) { }

  ngOnChanges(changes: SimpleChanges):void {
    if (changes.nsName || changes.nsTheme || changes.nsTwoToneColor) {
      this.changeIcon();
    }
  }

  protected changeIcon(): Promise<SVGElement | null> {
    return new Promise<SVGElement | null>((resolve, reject) => {
      if (!this.nsName) {
        this.clearSVGElement();
        resolve(null);
      } else {
        const preMeta: RenderMeta = {
          name: this.nsName,
          theme: this.nsTheme,
          twotoneColor: this.nsTwoToneColor
        }
        this.iconService.getRenderedContent(
          this.parseIconType(this.nsName, this.nsTheme),
          this.nsTwoToneColor
        )
      }
    })
  }

  /*
  解析标准的IconDefinition  或者用户使用 如account-book-fill  namespace:iconName 字符串加主题后缀的形式传入nsName
  */
  protected parseIconType(iconName: IconDefinition | string, theme: ThemeType): IconDefinition | string {
    if (isIconDefinition(iconName)) {
      return iconName;
    } else {
      // 判断是否是自命名图标 namespace:iconName 
      const [name, namespace] = getNameAndNamespace(iconName)
      if (namespace) {
        return name;
      }
      // 判断是否是 account-book-fill 已有theme后缀
      if (alreadyHasThemeSuffix(iconName)) {
        if (!!theme) {
          warn(`'nsName' ${name} already gets a theme inside so 'theme' ${theme} would be ignored`);
        }
        return name;
      } else {
        return withThemeSuffix(name, theme)
      }
    }
  }

  protected clearSVGElement():void {
    const el: HTMLElement = this.element.nativeElement;
    const children = el.childNodes;
    const length = children.length;
    for (let i = 0; i < length; i++) {
      const child = children[i] as any;
      if (child.tagName?.toLowerCase() === 'svg') {
        this.renderer.removeChild(el, child);
      }
    }
  }
}
